package Principal;

import Entidades.Barco;
import Entidades.Coordenada;
import Entidades.Orientacion;
import Entidades.Plano;
import Entidades.Planta;
import Entidades.Tablero;
import Implementacion.BatallaNaval;
import Implementacion.RobotDesastresImpl;
import Implementaciones.Cola;
import Implementaciones.Conjunto;
import Interfaces.RobotDesastresInterface;
import TDA.ColaTDA;
import TDA.ConjuntoTDA;

public class Principal {

	public static void main(String[] args) {
		/*
		 * PROBLEMA BATALLA NAVAL
		 */
//		demoBatallaNaval();

		/*
		 * PROBLEMA DE ROBOT PARA DESASTRES
		 */
		demoRobotDesastres();
	}

	public static Conjunto<Barco> completarBarcos() {
		Conjunto<Barco> barcos = new Conjunto<Barco>();
		barcos.inicializarConjunto();

		Barco b1 = new Barco();
		b1.setearDatos("B1", 1, Orientacion.Vertical);
		Barco b2 = new Barco();
		b2.setearDatos("B2", 1, Orientacion.Vertical);
		Barco b3 = new Barco();
		b3.setearDatos("B3", 1, Orientacion.Vertical);
		Barco b4 = new Barco();
		b4.setearDatos("B4", 3, Orientacion.Vertical);
		Barco b5 = new Barco();
		b5.setearDatos("B5", 5, Orientacion.Vertical);

		barcos.agregar(b1);
		barcos.agregar(b2);
		barcos.agregar(b3);
		barcos.agregar(b4);
		barcos.agregar(b5);

		return barcos;
	}

	public static Tablero obtenerTablero() {
		Tablero tablero = new Tablero(5);

		try {
			 tablero.setearValorEnfila(0, 2);
			 tablero.setearValorEnfila(1, 1);
			 tablero.setearValorEnfila(2, 2);
			 tablero.setearValorEnfila(3, 1);
			 tablero.setearValorEnfila(4, 3);
			 tablero.setearValorEnColumna(0, 4);
			 tablero.setearValorEnColumna(1, 0);
			 tablero.setearValorEnColumna(2, 1);
			 tablero.setearValorEnColumna(3, 3);
			 tablero.setearValorEnColumna(4, 1);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return tablero;
	}

	public static void imprimirTablero(Tablero tablero) {
		StringBuilder representacion = new StringBuilder();

		for (int i = 0; i < tablero.obtenerDimensionTablero(); i++) {
			for (int j = 0; j < tablero.obtenerDimensionTablero(); j++) {
				Barco barco = tablero.obtenerValor(i, j);
				String valorCelda = barco != null ? "[" + barco.obtenerNombre() + "]" : "[  ]";
				representacion.append(valorCelda);
			}
			representacion.append("\n");
		}

		System.out.println(representacion.toString());
	}

	public static void demoBatallaNaval() {
		BatallaNaval batallaNaval = new BatallaNaval();
		Conjunto<Barco> barcos = completarBarcos();
		Tablero tablero = obtenerTablero();
		batallaNaval.resolverBatallaNaval(barcos, tablero);

		System.out.println("Resultado Batalla Naval:\n");
		imprimirTablero(tablero);
	}

	public static void demoRobotDesastres() {
		RobotDesastresInterface robotDesastres = new RobotDesastresImpl();
		
		int cantPlantas = 2; // este valor puede ir variando
		Plano plano = armarPlano(cantPlantas);
		ConjuntoTDA<Coordenada> coordVictimas = completarCoordenadas();
		// Se devevuelve el resultado esperado
		ConjuntoTDA<Coordenada> victimasRescatadas = new Conjunto<Coordenada>();
		victimasRescatadas.inicializarConjunto();
		// Se devuelve el resultado esperado
		ColaTDA<Coordenada> secuenciaPuntosVisitados = new Cola<Coordenada>();
		secuenciaPuntosVisitados.inicializarCola();
		robotDesastres.RescatarVictimas(plano, coordVictimas, victimasRescatadas, secuenciaPuntosVisitados);
		imprimirResultadoRobot(victimasRescatadas, secuenciaPuntosVisitados);
	}

	public static Plano armarPlano(int cantPlantas) {
		Plano p = new Plano(cantPlantas);

		int n = 3;
		
		Planta primerPiso = new Planta(n, 0);
		
		primerPiso.setearAccesible(0, 0);
		primerPiso.setearAccesible(0, 1);
		primerPiso.setearAccesible(0, 2);
		primerPiso.setearInaccesible(1, 0);
		primerPiso.setearAccesible(1, 1);
		primerPiso.setearAccesible(1, 2);
		primerPiso.setearAccesible(2, 0);
		primerPiso.setearInaccesible(2, 1);
		primerPiso.setearAccesible(2, 2);
		
		Planta segundoPiso = new Planta(n, 1);
		
		segundoPiso.setearAccesible(0, 0);
		segundoPiso.setearAccesible(0, 1);
		segundoPiso.setearAccesible(0, 2);
		segundoPiso.setearAccesible(1, 0);
		segundoPiso.setearAccesible(1, 1);
		segundoPiso.setearAccesible(1, 2);
		segundoPiso.setearInaccesible(2, 0);
		segundoPiso.setearAccesible(2, 1);
		segundoPiso.setearAccesible(2, 2);
		
		try {			
			p.AgregarPlanta(primerPiso);
			p.AgregarPlanta(segundoPiso);			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return p;
	}

	public static ConjuntoTDA<Coordenada> completarCoordenadas() {
		ConjuntoTDA<Coordenada> c = new Conjunto<Coordenada>();
		c.inicializarConjunto();

		Coordenada c1 = new Coordenada();
		c1.setearPosicionX(2);
		c1.setearPosicionY(0);
		c1.setearNroPlanta(0);

		Coordenada c2 = new Coordenada();
		c2.setearPosicionX(2);
		c2.setearPosicionY(2);
		c2.setearNroPlanta(0);
		
		Coordenada c3 = new Coordenada();
		c3.setearPosicionX(2);
		c3.setearPosicionY(1);
		c3.setearNroPlanta(1);
		
		c.agregar(c1);
		c.agregar(c2);
		c.agregar(c3);
		
		return c;
	}

	public static void imprimirResultadoRobot(
			ConjuntoTDA<Coordenada> victimasRescatadas,
			ColaTDA<Coordenada> secuenciaPuntosVisitados) {

		System.out.println("\nResultados Robot Desastres: \n");
		System.out.println("Secuencia Puntos Visitados: " + caminoToString(secuenciaPuntosVisitados));
		System.out.println("Victimas Rescatadas: " + victimasToString(victimasRescatadas));
	}
	
	private static String coordenadaToString(Coordenada c) {		
		return "(" + c.obtenerPosicionX() + "," + c.obtenerPosicionY() + "," + c.obtenerNroPlanta() + ")";
	}
	
	private static String caminoToString(ColaTDA<Coordenada> camino) {		
		String caminoToString = "";
		
		ColaTDA<Coordenada> aux = new Cola<Coordenada>();
		aux.inicializarCola();
		
		while (!camino.colaVacia()) {
			Coordenada coord = camino.primero();
			caminoToString += coordenadaToString(coord) + " ";
			aux.acolar(coord);
			camino.desacolar();
		}

		while (!aux.colaVacia()) {
			Coordenada coord = aux.primero();
			camino.acolar(coord);
			aux.desacolar();
		}
		
		return caminoToString;
	}

	private static String victimasToString(ConjuntoTDA<Coordenada> victimasRescatadas) {
		String victimasToString = "";
		
		while (!victimasRescatadas.conjuntoVacio()) {
			Coordenada coordenada = victimasRescatadas.elegir();
			victimasToString += coordenadaToString(coordenada) + " ";
			victimasRescatadas.sacar(coordenada);
		}		
		
		return victimasToString;
	}

}
